/**  
* @Title:  HTMLContentParseUtils.java
* @Package com.hugedata.util
* @Description: TODO(用一句话描述该文件做什么)
* @author wangxiaoming
* @date  May 26, 2015 5:55:08 PM
* @version V1.0  
* Update Logs:
* ****************************************************
* Name:
* Date:
* Description:
******************************************************
*/
package com.hugedata.util;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import sun.misc.BASE64Decoder;
import us.codecraft.xsoup.Xsoup;
import us.codecraft.xsoup.xevaluator.XElements;

import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.hugedata.rule.HomeResultBean;
import com.hugedata.rule.SecondRule;
import com.hugedata.rule.TopRule;

/**
 * @ClassName: HTMLContentParseUtils
 * @Description: 网页内容解析工具
 * @author wangxiaoming
 * @date May 26, 2015 5:55:08 PM
 *
 */
public class HTMLContentParseUtils
{
    private static final Logger LOGGER = LoggerFactory.getLogger(HTMLContentParseUtils.class);
    
    /**
     * 
    * @Title: parseWebByRules
    * @Description: 根据规则解析网页源代码
    * @author wangxiaoming
    * @param jsonRules      解析规则--json字符串
    * @param webContentEncode   网页源代码--base64加密
    * @return
    * @throws
     */
    public static String parseWebByRules(String jsonRules,
            String webContentEncode)
    {
        String webContentDecode = null;
        try
        {
            byte[] webContentArr = new BASE64Decoder().decodeBuffer(webContentEncode);
            webContentDecode = new String(webContentArr, "UTF-8");
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        LOGGER.info("webContentDecode------{}", webContentDecode);
        if (StringUtils.isBlank(webContentDecode)
                || StringUtils.isBlank(jsonRules))
        {
            LOGGER.info("jsonRules or webContentEncode is null[empty]");
            return null;
        }
        
        HomeResultBean resultBean = new HomeResultBean();
        Class clazz = resultBean.getClass();
        Type type = new TypeToken<LinkedList<TopRule>>()
        {
        }.getType();
        Gson gson = new Gson();
        List<TopRule> ruleList = gson.fromJson(jsonRules, type);
        LOGGER.info("ruleList-----{}", ruleList);
        for (TopRule topRule : ruleList)
        {
            if (!topRule.isContainer())
            {
                continue;
            }
            else
            {
                String topXpath = topRule.getQuerys().getXpath();
                List<SecondRule> secondRules = topRule.getRules();
                Document document = Jsoup.parse(webContentDecode);
                List<String> childList = Xsoup.select(document, topXpath).list();
                for (String childStr : childList)
                {
                    if (StringUtils.isBlank(childStr))
                    {
                        continue;
                    }
                    else
                    {
                        for (SecondRule secondRule : secondRules)
                        {
                            String colName = secondRule.getName();
                            String secondXpath = secondRule.getQuerys().getXpath();
                            XElements secondEle = Xsoup.select(childStr, secondXpath);
                            String colValue;
                            if (secondRule.isBlock())
                            {
                                colValue = secondEle.getElements().text();
                            }
                            else if (secondRule.isTime())
                            {
                                String tempContent = secondEle.getElements().text();
                                colValue = grepTimeStr(tempContent);
                            }
                            else
                            {
                                colValue = secondEle.get();
                            }
                            
                            String setMethodName = new StringBuilder("set").append(colName.substring(0, 1).toUpperCase()).append(colName.substring(1)).toString();
                            Method method;
                            try
                            {
                                method = clazz.getMethod(setMethodName, String.class);
                                method.invoke(resultBean, colValue);
                            }
                            catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
                            {
                                LOGGER.error("", e);
                            }
                        }
                    }
                }
            }
        }
        return gson.toJson(resultBean);
    }
    
    private static final String YYYYMMDD = "yyyyMMdd";
    
    public static String grepTimeStr(String webContent)
    {
        String dateResult = null;
        try
        {
            dateResult = HTMLContentParseUtils.getDateTime(webContent);
        }
        catch (ParseException e)
        {
            e.printStackTrace();
            dateResult = "19700101";
        }
        return dateResult;
    }
     
     public static String getDateTime(String html) throws ParseException{  
         Calendar currentDate = Calendar.getInstance();
         
         //2015年05月27日  2015-05-27日
//         String regex = ".*((\\d{4}).*(\\d{2}).*(\\d{2})).*";
         String regex = ".*?((\\d{4})[\u4E00-\u9FA5-]*(\\d{2})[\u4E00-\u9FA5-]*(\\d{2})?).*";
         Pattern pattern = Pattern.compile(regex);
         Matcher matcher = pattern.matcher(html);
         if (matcher.matches())
         {
//             String group = matcher.group(1);
             String year = matcher.group(2);
             String month = matcher.group(3);
             String day = matcher.group(4);
             Date tmpDate = DateUtils.parseDate(year+month+day, YYYYMMDD);
             return DateFormatUtils.format(tmpDate, YYYYMMDD);
         }
         
        regex = ".*((\\d{4})[\u4E00-\u9FA5-]*(\\d{1})[\u4E00-\u9FA5-]*(\\d{2})?).*";
        pattern = Pattern.compile(regex);
        matcher = pattern.matcher(html);
        if (matcher.matches())
        {
            String year = matcher.group(2);
            String month = matcher.group(3);
            String day = matcher.group(4);
            Date tmpDate = DateUtils.parseDate(year + ("0" + month) + day, YYYYMMDD);
            return DateFormatUtils.format(tmpDate, YYYYMMDD);
        }
         
//         regex = ".*(\\d{1}).*(\\d{2}).*";
         regex = ".*(\\d{1})[\u4E00-\u9FA5.]*(\\d{2})[\u4E00-\u9FA5.]+.*";
         pattern = Pattern.compile(regex);
         matcher = pattern.matcher(html);
         if (matcher.matches())
         {
//             String group = matcher.group(1);
             String month = matcher.group(1);
             String day = matcher.group(2);
             Date tmpDate = currentDate.getTime();
             tmpDate = DateUtils.setMonths(tmpDate, NumberUtils.toInt(month)-1);
             tmpDate = DateUtils.setDays(tmpDate, NumberUtils.toInt(day));
//             Date tmpDate = DateUtils.parseDate("0" + month+day, MMDD);
             return DateFormatUtils.format(tmpDate, YYYYMMDD);
         }
         
         
         LOGGER.info("can not parse date from-----{}", html);
         Date defaultDate = DateUtils.setYears(currentDate.getTime(), 1970);
         defaultDate = DateUtils.setMonths(defaultDate, 0);
         defaultDate = DateUtils.setDays(defaultDate, 1);
         return DateFormatUtils.format(defaultDate, "yyyyMMdd");
     }  
     
     /** 
      * 得到网页中的时间问题 
      */  
     public static void getDateTimeBakFromWeb(String html){  
//         String html="更新时间：2009-3-23 13:14:31 作&nbsp;&nbsp;&nbsp;&nbsp;者更新时间：2009-3-23 13:12:54 作&nbsp;&nbsp;&nbsp;&nbsp;者更新时间：2009-3-16 17:39:54作&nbsp;&nbsp;&nbsp;&nbsp;者更新时间：2009-3-13 9:07:22作&nbsp;&nbsp;&nbsp;&nbsp;者更新时间：2009-3-9 13:41:51作&nbsp;&nbsp;&nbsp;&nbsp;者更新时间：2009-3-5 11:19:36作&nbsp;&nbsp;&nbsp;&nbsp;者更新时间：2009-3-5 11:16:33作&nbsp;&nbsp;&nbsp;&nbsp;者更新时间：2009-3-2 11:56:21作&nbsp;&nbsp;&nbsp;&nbsp;者更新时间：2009-2-26 10:30:19作&nbsp;&nbsp;&nbsp;&nbsp;者更新时间：2009-2-26 10:28:49更新时间";  
           
         // 这个正则表达式能抓取很多类型的日期时间，小到只有日期，大到日期时间（包括秒），这里是默认情况下提取。  
         //String regex=".*[^\\d]((\\d{4}|\\d{2}) ?[/年-] ?\\d{1,2} ?[/月-] ?\\d{1,2} ?[日 ]?( ?\\d{1,2}( ?[点:] ?\\d{1,2}( ?[分:] ?\\d{1,2} ?秒?)?)?)?)[^\\d].*";  
           
         //这里使用了贪婪限定符 ? 提取第一个时间  
         String regex=".*?[^\\d]((\\d{4}|\\d{2}) ?[/年-] ?\\d{1,2} ?[/月-] ?\\d{1,2} ?[日 ]?( ?\\d{1,2}( ?[点:] ?\\d{1,2}( ?[分:] ?\\d{1,2} ?秒?)?)?)?)[^\\d].*";  
           
         Pattern pattern = Pattern.compile(regex);  
         Matcher matcher = pattern.matcher(html);  
         if (matcher.matches()) {  
             System.out.println("得到第一个的时间是："+matcher.group(1));  
         }  
           
         //这里使用了贪婪限定符 ? 提取最后一个时间  
         regex=".*[^\\d]((\\d{4}|\\d{2}) ?[/年-] ?\\d{1,2} ?[/月-] ?\\d{1,2} ?[日 ]?( ?\\d{1,2}( ?[点:] ?\\d{1,2}( ?[分:] ?\\d{1,2} ?秒?)?)?)?)[^\\d].*?";       
         pattern = Pattern.compile(regex);  
         matcher = pattern.matcher(html);  
         if (matcher.matches()) {  
             System.out.println("得到最后一个的时间是："+matcher.group(1));  
         }  
     }  
}
